<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>React入门教程：从零开始构建你的第一个应用 | TechBlog</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/styles/github.min.css">
    <style>
        :root {
            /* 亮色主题变量 */
            --bg-color: #ffffff;
            --text-color: #24292f;
            --border-color: #d0d7de;
            --card-bg: #f6f8fa;
            --header-bg: #f6f8fa;
            --accent-color: #0969da;
            --accent-hover: #0550ae;
            --code-bg: rgba(175, 184, 193, 0.2);
            --shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
            --tag-bg: #ddf4ff;
            --tag-color: #0969da;
            --filter-bg: #f6f8fa;
            --input-bg: #ffffff;
            --toc-bg: #f6f8fa;
            --progress-color: #0969da;
            --toc-active-bg: rgba(9, 105, 218, 0.1);
            --toc-active-border: #0969da;
            --step-active-bg: #0969da;
            --step-active-color: #ffffff;
            --step-completed-bg: #ddf4ff;
            --step-completed-color: #0969da;
            --exercise-bg: #f6f8fa;
            --exercise-border: #d0d7de;
            --tip-bg: #fff8c5;
            --tip-border: #d4a72c;
            --warning-bg: #ffebe9;
            --warning-border: #cf222e;
        }

        .dark-theme {
            /* 深色主题变量 */
            --bg-color: #0d1117;
            --text-color: #e6edf3;
            --border-color: #30363d;
            --card-bg: #161b22;
            --header-bg: #161b22;
            --accent-color: #2f81f7;
            --accent-hover: #1c6bdb;
            --code-bg: rgba(110, 118, 129, 0.4);
            --shadow: 0 1px 3px rgba(0, 0, 0, 0.5), 0 1px 2px rgba(0, 0, 0, 0.7);
            --tag-bg: #388bfd26;
            --tag-color: #58a6ff;
            --filter-bg: #161b22;
            --input-bg: #0d1117;
            --toc-bg: #161b22;
            --progress-color: #2f81f7;
            --toc-active-bg: rgba(47, 129, 247, 0.15);
            --toc-active-border: #2f81f7;
            --step-active-bg: #2f81f7;
            --step-active-color: #ffffff;
            --step-completed-bg: rgba(47, 129, 247, 0.15);
            --step-completed-color: #58a6ff;
            --exercise-bg: #161b22;
            --exercise-border: #30363d;
            --tip-bg: rgba(187, 128, 9, 0.15);
            --tip-border: #bb8009;
            --warning-bg: rgba(248, 81, 73, 0.15);
            --warning-border: #f85149;
        }

        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            transition: background-color 0.3s, color 0.3s, border-color 0.3s;
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
            background-color: var(--bg-color);
            color: var(--text-color);
            line-height: 1.6;
        }

        .container {
            max-width: 1280px;
            margin: 0 auto;
            padding: 0 20px;
        }

        /* 头部导航 */
        header {
            background-color: var(--header-bg);
            border-bottom: 1px solid var(--border-color);
            position: sticky;
            top: 0;
            z-index: 100;
        }

        .navbar {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 16px 0;
            position: relative;
        }

        .logo {
            display: flex;
            align-items: center;
            gap: 10px;
            font-weight: 600;
            font-size: 20px;
            color: var(--text-color);
            text-decoration: none;
            z-index: 101;
        }

        .logo i {
            color: var(--accent-color);
        }

        .nav-links {
            display: flex;
            gap: 24px;
        }

        .nav-links a {
            color: var(--text-color);
            text-decoration: none;
            font-size: 14px;
            font-weight: 500;
            transition: all 0.2s ease;
        }

        .nav-links a:hover {
            color: var(--accent-color);
        }

        .nav-links a.active {
            color: var(--accent-color);
            font-weight: 600;
        }

        .nav-actions {
            display: flex;
            align-items: center;
            gap: 12px;
        }

        .theme-toggle {
            background: none;
            border: 1px solid var(--border-color);
            border-radius: 6px;
            padding: 8px 12px;
            color: var(--text-color);
            cursor: pointer;
            display: flex;
            align-items: center;
            gap: 6px;
            font-size: 14px;
            transition: all 0.2s ease;
        }

        .theme-toggle:hover {
            background-color: var(--code-bg);
        }

        .mobile-menu {
            display: none;
            background: none;
            border: 1px solid var(--border-color);
            border-radius: 6px;
            color: var(--text-color);
            cursor: pointer;
            padding: 8px 12px;
            font-size: 16px;
            transition: all 0.2s ease;
        }

        .mobile-menu:hover {
            background-color: var(--code-bg);
        }

        /* 阅读进度条 */
        .reading-progress {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 3px;
            background: transparent;
            z-index: 99;
        }

        .reading-progress-bar {
            height: 100%;
            background: var(--progress-color);
            width: 0%;
            transition: width 0.2s ease;
        }

        /* 主要内容区域 */
        .main-content {
            display: flex;
            flex-direction: column;
            gap: 24px;
            padding: 32px 0;
        }

        /* 教程头部区域 */
        .tutorial-header {
            margin-bottom: 16px;
        }

        .tutorial-title {
            font-size: 32px;
            font-weight: 700;
            margin-bottom: 16px;
            line-height: 1.3;
        }

        .tutorial-meta {
            display: flex;
            gap: 20px;
            margin-bottom: 20px;
            font-size: 14px;
            color: var(--text-color);
            opacity: 0.8;
            flex-wrap: wrap;
        }

        .tutorial-tags {
            display: flex;
            gap: 8px;
            margin-bottom: 20px;
            flex-wrap: wrap;
        }

        .tag {
            background-color: var(--tag-bg);
            color: var(--tag-color);
            padding: 4px 10px;
            border-radius: 12px;
            font-size: 12px;
            font-weight: 500;
        }

        .difficulty {
            display: inline-flex;
            align-items: center;
            gap: 4px;
            padding: 4px 10px;
            border-radius: 12px;
            font-size: 12px;
            font-weight: 500;
        }

        .difficulty.beginner {
            background-color: rgba(40, 167, 69, 0.1);
            color: var(--beginner-color, #28a745);
        }

        .difficulty.intermediate {
            background-color: rgba(255, 193, 7, 0.1);
            color: var(--intermediate-color, #ffc107);
        }

        .difficulty.advanced {
            background-color: rgba(220, 53, 69, 0.1);
            color: var(--advanced-color, #dc3545);
        }

        /* 内容容器 */
        .content-container {
            display: flex;
            gap: 32px;
            align-items: flex-start;
        }

        /* 教程内容区域 */
        .tutorial-content {
            flex: 1;
            min-width: 0;
            background-color: var(--card-bg);
            border: 1px solid var(--border-color);
            border-radius: 6px;
            padding: 32px;
        }

        /* 教程正文样式 */
        .tutorial-body {
            font-size: 16px;
            line-height: 1.7;
        }

        .tutorial-body h2 {
            font-size: 24px;
            font-weight: 600;
            margin: 32px 0 16px;
            padding-bottom: 8px;
            border-bottom: 1px solid var(--border-color);
        }

        .tutorial-body h3 {
            font-size: 20px;
            font-weight: 600;
            margin: 24px 0 12px;
        }

        .tutorial-body p {
            margin-bottom: 16px;
        }

        .tutorial-body ul,
        .tutorial-body ol {
            margin-bottom: 16px;
            padding-left: 24px;
        }

        .tutorial-body li {
            margin-bottom: 8px;
        }

        .tutorial-body blockquote {
            border-left: 4px solid var(--accent-color);
            padding-left: 16px;
            margin: 20px 0;
            font-style: italic;
            background-color: var(--code-bg);
            padding: 16px;
            border-radius: 0 6px 6px 0;
        }

        /* 代码块样式 */
        .dark-theme .tutorial-body pre {
            background-color: #0d1117;
        }

        .tutorial-body pre {
            background-color: var(--code-bg);
            border-radius: 6px;
            padding: 16px;
            overflow-x: auto;
            margin: 20px 0;
            font-size: 14px;
            border: 1px solid var(--border-color);
        }

        .tutorial-body code {
            font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
            background-color: var(--code-bg);
            padding: 2px 6px;
            border-radius: 4px;
            font-size: 14px;
        }

        .tutorial-body pre code {
            background: none;
            padding: 0;
        }

        .tutorial-body img {
            max-width: 100%;
            height: auto;
            border-radius: 6px;
            margin: 20px 0;
            border: 1px solid var(--border-color);
        }

        .tutorial-body table {
            width: 100%;
            border-collapse: collapse;
            margin: 20px 0;
        }

        .tutorial-body th,
        .tutorial-body td {
            padding: 12px;
            text-align: left;
            border-bottom: 1px solid var(--border-color);
        }

        .tutorial-body th {
            background-color: var(--code-bg);
            font-weight: 600;
        }

        /* 步骤导航 */
        .steps-navigation {
            display: flex;
            justify-content: space-between;
            margin: 40px 0;
            padding: 20px 0;
            border-top: 1px solid var(--border-color);
            border-bottom: 1px solid var(--border-color);
        }

        .step-btn {
            display: flex;
            align-items: center;
            gap: 8px;
            padding: 10px 16px;
            background-color: var(--code-bg);
            color: var(--text-color);
            text-decoration: none;
            border-radius: 6px;
            transition: all 0.2s ease;
        }

        .step-btn:hover {
            background-color: var(--accent-color);
            color: white;
        }

        .step-btn.prev {
            text-align: left;
        }

        .step-btn.next {
            text-align: right;
            margin-left: auto;
        }

        /* 步骤指示器 */
        .steps-indicator {
            display: flex;
            justify-content: center;
            margin: 30px 0;
            gap: 8px;
        }

        .step-dot {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            background-color: var(--border-color);
            transition: all 0.3s ease;
        }

        .step-dot.active {
            background-color: var(--step-active-bg);
            transform: scale(1.2);
        }

        .step-dot.completed {
            background-color: var(--step-completed-bg);
        }

        /* 练习区域 */
        .exercise {
            background-color: var(--exercise-bg);
            border: 1px solid var(--exercise-border);
            border-radius: 6px;
            padding: 20px;
            margin: 24px 0;
        }

        .exercise-header {
            display: flex;
            align-items: center;
            gap: 8px;
            margin-bottom: 16px;
        }

        .exercise-icon {
            color: var(--accent-color);
            font-size: 18px;
        }

        .exercise-title {
            font-size: 18px;
            font-weight: 600;
        }

        .exercise-content {
            margin-bottom: 16px;
        }

        .exercise-actions {
            display: flex;
            gap: 12px;
        }

        .exercise-btn {
            padding: 8px 16px;
            border: 1px solid var(--border-color);
            border-radius: 6px;
            background-color: var(--bg-color);
            color: var(--text-color);
            cursor: pointer;
            transition: all 0.2s ease;
            font-size: 14px;
        }

        .exercise-btn:hover {
            background-color: var(--accent-color);
            color: white;
            border-color: var(--accent-color);
        }

        .exercise-btn.primary {
            background-color: var(--accent-color);
            color: white;
            border-color: var(--accent-color);
        }

        .exercise-btn.primary:hover {
            background-color: var(--accent-hover);
            border-color: var(--accent-hover);
        }

        /* 提示和警告框 */
        .tip-box,
        .warning-box {
            padding: 16px;
            border-radius: 6px;
            margin: 20px 0;
            border-left: 4px solid;
        }

        .tip-box {
            background-color: var(--tip-bg);
            border-color: var(--tip-border);
        }

        .warning-box {
            background-color: var(--warning-bg);
            border-color: var(--warning-border);
        }

        .tip-box h4,
        .warning-box h4 {
            display: flex;
            align-items: center;
            gap: 8px;
            margin-bottom: 8px;
            font-size: 16px;
        }

        /* 教程操作栏 */
        .tutorial-actions {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin: 30px 0;
            padding: 16px;
            background-color: var(--filter-bg);
            border: 1px solid var(--border-color);
            border-radius: 6px;
        }

        .action-buttons {
            display: flex;
            gap: 12px;
        }

        .action-btn {
            display: flex;
            align-items: center;
            gap: 6px;
            padding: 8px 16px;
            background-color: var(--code-bg);
            color: var(--text-color);
            border: 1px solid var(--border-color);
            border-radius: 6px;
            cursor: pointer;
            transition: all 0.2s ease;
            font-size: 14px;
        }

        .action-btn:hover {
            background-color: var(--accent-color);
            color: white;
            border-color: var(--accent-color);
        }

        .action-btn.liked,
        .action-btn.bookmarked {
            background-color: var(--accent-color);
            color: white;
            border-color: var(--accent-color);
        }

        .share-options {
            display: flex;
            gap: 8px;
        }

        .share-btn {
            display: flex;
            align-items: center;
            justify-content: center;
            width: 36px;
            height: 36px;
            border-radius: 50%;
            background-color: var(--code-bg);
            color: var(--text-color);
            border: none;
            cursor: pointer;
            transition: all 0.2s ease;
        }

        .share-btn:hover {
            background-color: var(--accent-color);
            color: white;
        }

        /* 目录区域 */
        .toc-container {
            width: 280px;
            flex-shrink: 0;
            position: sticky;
            top: 100px;
            max-height: calc(100vh - 140px);
            overflow-y: auto;
        }

        .toc-card {
            background-color: var(--card-bg);
            border: 1px solid var(--border-color);
            border-radius: 6px;
            padding: 20px;
        }

        .toc-title {
            font-size: 16px;
            font-weight: 600;
            margin-bottom: 16px;
            padding-bottom: 8px;
            border-bottom: 1px solid var(--border-color);
        }

        .toc-list {
            list-style: none;
        }

        .toc-item {
            margin-bottom: 8px;
            position: relative;
        }

        .toc-link {
            color: var(--text-color);
            text-decoration: none;
            font-size: 14px;
            transition: all 0.3s ease;
            display: block;
            padding: 8px 12px;
            border-radius: 4px;
            border-left: 3px solid transparent;
            position: relative;
            overflow: hidden;
        }

        .toc-link::before {
            content: '';
            position: absolute;
            top: 0;
            left: -100%;
            width: 100%;
            height: 100%;
            background: linear-gradient(90deg, transparent, var(--toc-active-bg), transparent);
            transition: left 0.5s ease;
        }

        .toc-link:hover {
            background-color: var(--toc-active-bg);
            color: var(--accent-color);
            border-left-color: var(--accent-color);
        }

        .toc-link.active {
            background-color: var(--toc-active-bg);
            color: var(--accent-color);
            font-weight: 600;
            border-left-color: var(--toc-active-border);
            transform: translateX(5px);
        }

        .toc-link.active::before {
            left: 100%;
        }

        .toc-sublist {
            list-style: none;
            padding-left: 16px;
            margin-top: 4px;
        }

        .toc-sublist .toc-link {
            font-size: 13px;
            padding: 6px 12px;
        }

        /* 相关教程 */
        .related-tutorials {
            margin-top: 40px;
        }

        .section-title {
            font-size: 24px;
            font-weight: 600;
            margin-bottom: 20px;
            padding-bottom: 12px;
            border-bottom: 1px solid var(--border-color);
        }

        .related-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
            gap: 20px;
        }

        .related-card {
            background-color: var(--card-bg);
            border: 1px solid var(--border-color);
            border-radius: 6px;
            padding: 20px;
            transition: border-color 0.2s ease;
        }

        .related-card:hover {
            border-color: var(--accent-color);
        }

        .related-title {
            font-size: 18px;
            font-weight: 600;
            margin-bottom: 8px;
        }

        .related-title a {
            color: var(--accent-color);
            text-decoration: none;
        }

        .related-title a:hover {
            text-decoration: underline;
        }

        .related-meta {
            display: flex;
            gap: 12px;
            margin-bottom: 12px;
            font-size: 13px;
            opacity: 0.8;
        }

        .related-excerpt {
            font-size: 14px;
            line-height: 1.5;
        }

        /* 页脚 */
        footer {
            border-top: 1px solid var(--border-color);
            padding: 32px 0;
            text-align: center;
            font-size: 14px;
            color: var(--text-color);
            opacity: 0.8;
        }

        /* 添加GitHub深色主题的代码高亮样式 */
        .dark-theme .hljs {
            color: #c9d1d9;
            background: #0d1117;
        }

        .dark-theme .hljs-doctag,
        .dark-theme .hljs-keyword,
        .dark-theme .hljs-meta .hljs-keyword,
        .dark-theme .hljs-template-tag,
        .dark-theme .hljs-template-variable,
        .dark-theme .hljs-type,
        .dark-theme .hljs-variable.language_ {
            color: #ff7b72;
        }

        .dark-theme .hljs-title,
        .dark-theme .hljs-title.class_,
        .dark-theme .hljs-title.class_.inherited__,
        .dark-theme .hljs-title.function_ {
            color: #d2a8ff;
        }

        .dark-theme .hljs-attr,
        .dark-theme .hljs-attribute,
        .dark-theme .hljs-literal,
        .dark-theme .hljs-meta,
        .dark-theme .hljs-number,
        .dark-theme .hljs-operator,
        .dark-theme .hljs-variable,
        .dark-theme .hljs-selector-attr,
        .dark-theme .hljs-selector-class,
        .dark-theme .hljs-selector-id {
            color: #79c0ff;
        }

        .dark-theme .hljs-regexp,
        .dark-theme .hljs-string,
        .dark-theme .hljs-meta .hljs-string {
            color: #a5d6ff;
        }

        .dark-theme .hljs-built_in,
        .dark-theme .hljs-symbol {
            color: #ffa657;
        }

        .dark-theme .hljs-comment,
        .dark-theme .hljs-code,
        .dark-theme .hljs-formula {
            color: #8b949e;
        }

        .dark-theme .hljs-name,
        .dark-theme .hljs-quote,
        .dark-theme .hljs-selector-tag,
        .dark-theme .hljs-selector-pseudo {
            color: #7ee787;
        }

        .dark-theme .hljs-subst {
            color: #c9d1d9;
        }

        .dark-theme .hljs-section {
            color: #1f6feb;
            font-weight: bold;
        }

        .dark-theme .hljs-bullet {
            color: #f2cc60;
        }

        .dark-theme .hljs-emphasis {
            color: #c9d1d9;
            font-style: italic;
        }

        .dark-theme .hljs-strong {
            color: #c9d1d9;
            font-weight: bold;
        }

        .dark-theme .hljs-addition {
            color: #aff5b4;
            background-color: #033a16;
        }

        .dark-theme .hljs-deletion {
            color: #ffdcd7;
            background-color: #67060c;
        }

        /* 响应式设计优化 */
        @media (max-width: 1024px) {
            .content-container {
                gap: 24px;
            }

            .toc-container {
                width: 250px;
            }
        }

        @media (max-width: 900px) {
            .content-container {
                flex-direction: column;
            }

            .toc-container {
                width: 100%;
                order: -1;
                margin-bottom: 24px;
                position: static;
            }

            .toc-card {
                padding: 16px;
            }
        }

        @media (max-width: 768px) {
            .container {
                padding: 0 16px;
            }

            .navbar {
                padding: 12px 0;
            }

            .logo {
                font-size: 18px;
            }

            .nav-links {
                position: absolute;
                top: 100%;
                left: 0;
                width: 100%;
                background-color: var(--header-bg);
                border-top: 1px solid var(--border-color);
                flex-direction: column;
                padding: 16px 20px;
                display: none;
                box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
            }

            .nav-links.active {
                display: flex;
            }

            .nav-links a {
                padding: 12px 0;
                border-bottom: 1px solid var(--border-color);
                font-size: 16px;
            }

            .nav-links a:last-child {
                border-bottom: none;
            }

            .mobile-menu {
                display: block;
                min-height: 44px;
                min-width: 44px;
                display: flex;
                align-items: center;
                justify-content: center;
            }

            .theme-toggle,
            .mobile-menu {
                padding: 10px 14px;
            }

            .main-content {
                padding: 24px 0;
                gap: 20px;
            }

            .content-container {
                gap: 20px;
            }

            .tutorial-title {
                font-size: 24px;
            }

            .tutorial-content {
                padding: 20px;
                overflow: hidden;
                width: 100%;
                max-width: 100%;
            }

            .tutorial-body {
                font-size: 15px;
                max-width: 100%;
                overflow-x: hidden;
                word-wrap: break-word;
            }

            .tutorial-body h2 {
                font-size: 20px;
            }

            .tutorial-body h3 {
                font-size: 18px;
            }

            .tutorial-meta {
                flex-direction: column;
                gap: 8px;
            }

            .tutorial-actions {
                flex-direction: column;
                gap: 16px;
                align-items: stretch;
            }

            .action-buttons {
                justify-content: center;
            }

            .share-options {
                justify-content: center;
            }

            .related-grid {
                grid-template-columns: 1fr;
            }

            /* 修改步骤导航为垂直布局 */
            .steps-navigation {
                flex-direction: column;
                gap: 12px;
                margin-top: 32px;
                padding-top: 20px;
            }

            .step-btn {
                max-width: 100%;
                width: 100%;
                justify-content: center;
                text-align: center;
                padding: 12px 16px;
            }

            .step-btn.prev {
                text-align: center;
                order: 1;
            }

            .step-btn.next {
                text-align: center;
                margin-left: 0;
                order: 2;
            }

            /* 调整按钮内图标位置 */
            .step-btn.prev i {
                order: 1;
                margin-right: 8px;
            }

            .step-btn.prev span {
                order: 2;
            }

            .step-btn.next i {
                order: 2;
                margin-left: 8px;
            }

            .step-btn.next span {
                order: 1;
            }

            /* 文本内容自动换行 */
            .tutorial-body p,
            .tutorial-body li,
            .tutorial-body blockquote,
            .tutorial-body h2,
            .tutorial-body h3 {
                word-wrap: break-word;
                overflow-wrap: break-word;
                hyphens: auto;
            }

            /* 代码块保持横向滚动 */
            .tutorial-body pre {
                overflow-x: auto;
                max-width: 100%;
                font-size: 13px;
                padding: 12px;
                -webkit-overflow-scrolling: touch;
            }

            /* 表格横向滚动 */
            .tutorial-body table {
                display: block;
                overflow-x: auto;
                white-space: nowrap;
                max-width: 100%;
            }

            /* 图片限制宽度 */
            .tutorial-body img {
                max-width: 100%;
                height: auto;
            }

            /* 减少移动端的动画效果 */
            * {
                transition: none;
            }

            /* 保留必要的过渡 */
            .theme-toggle,
            .mobile-menu,
            .nav-links a,
            .action-btn,
            .share-btn,
            .step-btn {
                transition: all 0.2s ease;
            }

            /* 移动端目录样式优化 */
            .toc-link {
                padding: 10px 12px;
            }
        }

        @media (max-width: 480px) {
            .tutorial-tags {
                gap: 6px;
            }

            .container {
                padding: 0 12px;
            }

            .content-container {
                gap: 16px;
            }

            /* 小屏幕下的步骤导航按钮优化 */
            .steps-navigation {
                gap: 10px;
            }

            .step-btn {
                padding: 10px 12px;
                font-size: 14px;
            }

            /* 确保按钮文字不会太长 */
            .step-btn span {
                display: -webkit-box;
                -webkit-line-clamp: 1;
                line-clamp: 1;
                -webkit-box-orient: vertical;
                overflow: hidden;
                text-overflow: ellipsis;
            }

            /* 小屏幕下调整图标大小 */
            .step-btn i {
                font-size: 12px;
            }
        }

        @media (max-height: 500px) and (orientation: landscape) {
            .navbar {
                padding: 8px 0;
            }

            .main-content {
                padding: 16px 0;
            }

            .tutorial-content {
                padding: 16px;
            }
        }

        /* 确保代码块在移动端不会溢出 */
        pre code {
            white-space: pre;
            word-wrap: normal;
        }
    </style>
</head>

<body class="light-theme">
    <!-- 阅读进度条 -->
    <div class="reading-progress">
        <div class="reading-progress-bar" id="progressBar"></div>
    </div>

    <header>
        <div class="container">
            <nav class="navbar">
                <a href="index.html" class="logo">
                    <i class="fas fa-code"></i>
                    TechBlog
                </a>

                <div class="nav-links">
                    <a href="index.html">首页</a>
                    <a href="article-list.html">文章</a>
                    <a href="tutorial-list.html" class="active">教程</a>
                    <a href="projects.html">项目</a>
                    <a href="about.html">关于</a>
                </div>

                <div class="nav-actions">
                    <button class="theme-toggle" id="themeToggle">
                        <i class="fas fa-moon"></i>
                        <span>深色模式</span>
                    </button>
                    <button class="mobile-menu" id="mobileMenu">
                        <i class="fas fa-bars"></i>
                    </button>
                </div>
            </nav>
        </div>
    </header>

    <div class="container">
        <div class="main-content">
            <!-- 教程头部 -->
            <div class="tutorial-header">
                <h1 class="tutorial-title">React入门教程：从零开始构建你的第一个应用</h1>
                <div class="tutorial-meta">
                    <span><i class="far fa-calendar"></i> 2023-10-20</span>
                    <span><i class="far fa-clock"></i> 45分钟</span>
                    <span><i class="far fa-eye"></i> 850浏览</span>
                    <span><i class="far fa-user"></i> 张明</span>
                    <span class="difficulty beginner"><i class="fas fa-signal"></i> 入门</span>
                </div>
                <div class="tutorial-tags">
                    <span class="tag">React</span>
                    <span class="tag">JavaScript</span>
                    <span class="tag">前端</span>
                    <span class="tag">入门</span>
                </div>
            </div>

            <!-- 教程操作栏 -->
            <div class="tutorial-actions">
                <div class="action-buttons">
                    <button class="action-btn" id="likeBtn">
                        <i class="far fa-thumbs-up"></i> 点赞
                    </button>
                    <button class="action-btn" id="bookmarkBtn">
                        <i class="far fa-bookmark"></i> 收藏
                    </button>
                    <button class="action-btn" id="completedBtn">
                        <i class="far fa-check-circle"></i> 标记完成
                    </button>
                </div>
                <div class="share-options">
                    <button class="share-btn" title="分享到Twitter">
                        <i class="fab fa-twitter"></i>
                    </button>
                    <button class="share-btn" title="分享到LinkedIn">
                        <i class="fab fa-linkedin-in"></i>
                    </button>
                    <button class="share-btn" title="复制链接">
                        <i class="fas fa-link"></i>
                    </button>
                </div>
            </div>

            <!-- 内容区域和目录 -->
            <div class="content-container">
                <!-- 教程内容 -->
                <article class="tutorial-content">
                    <div class="tutorial-body">
                        <p>本教程适合React初学者，通过实际项目带你了解React的基本概念，包括组件、状态和属性。我们将一步步构建一个简单的待办事项应用。</p>

                        <h2 id="prerequisites">前置要求</h2>
                        <p>在开始本教程之前，请确保你已经具备以下知识：</p>
                        <ul>
                            <li>基本的HTML、CSS和JavaScript知识</li>
                            <li>了解ES6语法（箭头函数、解构、模块等）</li>
                            <li>已安装Node.js和npm</li>
                        </ul>

                        <h2 id="setup">环境设置</h2>
                        <p>首先，我们需要设置React开发环境。最简单的方法是使用Create React App工具。</p>

                        <div class="tip-box">
                            <h4><i class="fas fa-lightbulb"></i> 提示</h4>
                            <p>Create React App是Facebook官方推荐的React应用创建工具，它配置了所有必要的构建工具，让你可以专注于代码而不是配置。</p>
                        </div>

                        <h3 id="install-cra">安装Create React App</h3>
                        <p>打开终端并运行以下命令：</p>
                        <pre><code class="language-bash">npx create-react-app my-todo-app
cd my-todo-app
npm start</code></pre>
                        <p>这将在<code>my-todo-app</code>目录中创建一个新的React应用，并启动开发服务器。你可以在浏览器中打开<code>http://localhost:3000</code>查看应用。
                        </p>

                        <h2 id="understanding-components">理解React组件</h2>
                        <p>React应用由组件构成。组件是返回React元素的JavaScript函数或类。</p>

                        <h3 id="functional-components">函数组件</h3>
                        <p>最简单的React组件是函数组件：</p>
                        <pre><code class="language-jsx">function Welcome() {
  return &lt;h1&gt;Hello, World!&lt;/h1&gt;;
}</code></pre>
                        <p>或者使用箭头函数：</p>
                        <pre><code class="language-jsx">const Welcome = () => {
  return &lt;h1&gt;Hello, World!&lt;/h1&gt;;
};</code></pre>

                        <h3 id="jsx-syntax">JSX语法</h3>
                        <p>JSX是JavaScript的语法扩展，允许我们在JavaScript中编写类似HTML的代码。JSX使React组件的编写更加直观。</p>
                        <p>JSX规则：</p>
                        <ul>
                            <li>所有标签必须闭合</li>
                            <li>使用className而不是class</li>
                            <li>组件名称必须以大写字母开头</li>
                        </ul>

                        <div class="exercise">
                            <div class="exercise-header">
                                <i class="fas fa-pencil-alt exercise-icon"></i>
                                <h3 class="exercise-title">练习1：创建你的第一个组件</h3>
                            </div>
                            <div class="exercise-content">
                                <p>在<code>src</code>文件夹中创建一个名为<code>Welcome.js</code>的新文件，并编写一个简单的Welcome组件，显示"欢迎学习React!"。
                                </p>
                            </div>
                            <div class="exercise-actions">
                                <button class="exercise-btn">查看答案</button>
                                <button class="exercise-btn primary">标记完成</button>
                            </div>
                        </div>

                        <h2 id="props-and-state">Props和State</h2>
                        <p>Props和State是React中两个核心概念，用于管理组件的数据。</p>

                        <h3 id="understanding-props">理解Props</h3>
                        <p>Props（属性）是从父组件传递给子组件的数据。Props是只读的，不能在子组件中修改。</p>
                        <pre><code class="language-jsx">function Welcome(props) {
  return &lt;h1&gt;Hello, {props.name}!&lt;/h1&gt;;
}

// 使用组件
&lt;Welcome name="Alice" /&gt;</code></pre>

                        <h3 id="understanding-state">理解State</h3>
                        <p>State是组件内部管理的数据，可以随时间变化。当State改变时，组件会重新渲染。</p>
                        <p>在函数组件中，我们使用useState Hook来添加State：</p>
                        <pre><code class="language-jsx">import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);
  
  return (
    &lt;div&gt;
      &lt;p&gt;You clicked {count} times&lt;/p&gt;
      &lt;button onClick={() => setCount(count + 1)}&gt;
        Click me
      &lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre>

                        <div class="warning-box">
                            <h4><i class="fas fa-exclamation-triangle"></i> 注意</h4>
                            <p>不要直接修改State。使用setState函数（或useState的setter函数）来更新State，这样才能确保组件正确重新渲染。</p>
                        </div>

                        <h2 id="building-todo-app">构建待办事项应用</h2>
                        <p>现在我们已经了解了React的基本概念，让我们开始构建一个简单的待办事项应用。</p>

                        <h3 id="project-structure">项目结构</h3>
                        <p>我们的应用将包含以下组件：</p>
                        <ul>
                            <li>TodoApp - 主组件</li>
                            <li>TodoList - 显示待办事项列表</li>
                            <li>TodoItem - 单个待办事项</li>
                            <li>AddTodo - 添加新待办事项的表单</li>
                        </ul>

                        <h3 id="implementing-components">实现组件</h3>
                        <p>首先，我们创建TodoItem组件：</p>
                        <pre><code class="language-jsx">function TodoItem({ todo, toggleTodo, deleteTodo }) {
  return (
    &lt;div className="todo-item"&gt;
      &lt;input 
        type="checkbox" 
        checked={todo.completed} 
        onChange={() => toggleTodo(todo.id)} 
      /&gt;
      &lt;span style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}&gt;
        {todo.text}
      &lt;/span&gt;
      &lt;button onClick={() => deleteTodo(todo.id)}&gt;删除&lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre>

                        <p>接下来，创建TodoList组件：</p>
                        <pre><code class="language-jsx">function TodoList({ todos, toggleTodo, deleteTodo }) {
  return (
    &lt;div className="todo-list"&gt;
      {todos.map(todo => (
        &lt;TodoItem 
          key={todo.id} 
          todo={todo} 
          toggleTodo={toggleTodo}
          deleteTodo={deleteTodo}
        /&gt;
      ))}
    &lt;/div&gt;
  );
}</code></pre>

                        <h2 id="handling-events">处理事件</h2>
                        <p>React中的事件处理与DOM事件处理类似，但有一些语法差异：</p>
                        <ul>
                            <li>React事件使用驼峰命名法（如onClick）</li>
                            <li>在JSX中传递函数作为事件处理器</li>
                        </ul>

                        <h3 id="form-handling">表单处理</h3>
                        <p>在React中，表单元素通常作为受控组件来实现：</p>
                        <pre><code class="language-jsx">function AddTodo({ addTodo }) {
  const [text, setText] = useState('');
  
  const handleSubmit = (e) => {
    e.preventDefault();
    if (text.trim()) {
      addTodo(text);
      setText('');
    }
  };
  
  return (
    &lt;form onSubmit={handleSubmit}&gt;
      &lt;input 
        type="text" 
        value={text} 
        onChange={(e) => setText(e.target.value)} 
        placeholder="添加新任务..." 
      /&gt;
      &lt;button type="submit"&gt;添加&lt;/button&gt;
    &lt;/form&gt;
  );
}</code></pre>

                        <h2 id="final-app">完整应用</h2>
                        <p>最后，我们将所有组件组合在一起：</p>
                        <pre><code class="language-jsx">function TodoApp() {
  const [todos, setTodos] = useState([]);
  
  const addTodo = (text) => {
    const newTodo = {
      id: Date.now(),
      text,
      completed: false
    };
    setTodos([...todos, newTodo]);
  };
  
  const toggleTodo = (id) => {
    setTodos(todos.map(todo => 
      todo.id === id ? { ...todo, completed: !todo.completed } : todo
    ));
  };
  
  const deleteTodo = (id) => {
    setTodos(todos.filter(todo => todo.id !== id));
  };
  
  return (
    &lt;div className="todo-app"&gt;
      &lt;h1&gt;我的待办事项&lt;/h1&gt;
      &lt;AddTodo addTodo={addTodo} /&gt;
      &lt;TodoList 
        todos={todos} 
        toggleTodo={toggleTodo}
        deleteTodo={deleteTodo}
      /&gt;
    &lt;/div&gt;
  );
}</code></pre>

                        <div class="exercise">
                            <div class="exercise-header">
                                <i class="fas fa-pencil-alt exercise-icon"></i>
                                <h3 class="exercise-title">练习2：增强待办事项应用</h3>
                            </div>
                            <div class="exercise-content">
                                <p>尝试为待办事项应用添加以下功能：</p>
                                <ul>
                                    <li>显示未完成事项的数量</li>
                                    <li>添加筛选功能（全部/已完成/未完成）</li>
                                    <li>添加本地存储，使数据在页面刷新后仍然存在</li>
                                </ul>
                            </div>
                            <div class="exercise-actions">
                                <button class="exercise-btn">查看答案</button>
                                <button class="exercise-btn primary">标记完成</button>
                            </div>
                        </div>

                        <h2 id="conclusion">总结</h2>
                        <p>恭喜！你已经完成了第一个React应用。通过本教程，你学会了：</p>
                        <ul>
                            <li>如何设置React开发环境</li>
                            <li>React组件的基本概念</li>
                            <li>Props和State的使用</li>
                            <li>事件处理和表单控制</li>
                            <li>构建一个完整的待办事项应用</li>
                        </ul>
                        <p>React是一个强大的库，还有更多高级概念等待你去探索，如Hooks、Context API、路由等。继续学习，你将能够构建更复杂的应用！</p>
                    </div>

                    <!-- 步骤导航 -->
                    <div class="steps-navigation">
                        <a href="#" class="step-btn prev">
                            <i class="fas fa-arrow-left"></i>
                            <span>上一篇：JavaScript基础语法</span>
                        </a>
                        <a href="#" class="step-btn next">
                            <span>下一篇：React Hooks深入理解</span>
                            <i class="fas fa-arrow-right"></i>
                        </a>
                    </div>

                    <!-- 步骤指示器 -->
                    <div class="steps-indicator">
                        <div class="step-dot completed"></div>
                        <div class="step-dot completed"></div>
                        <div class="step-dot active"></div>
                        <div class="step-dot"></div>
                        <div class="step-dot"></div>
                    </div>
                </article>

                <!-- 目录 -->
                <aside class="toc-container">
                    <div class="toc-card">
                        <h3 class="toc-title">目录</h3>
                        <ul class="toc-list">
                            <li class="toc-item">
                                <a href="#prerequisites" class="toc-link">前置要求</a>
                            </li>
                            <li class="toc-item">
                                <a href="#setup" class="toc-link">环境设置</a>
                                <ul class="toc-sublist">
                                    <li class="toc-item">
                                        <a href="#install-cra" class="toc-link">安装Create React App</a>
                                    </li>
                                </ul>
                            </li>
                            <li class="toc-item">
                                <a href="#understanding-components" class="toc-link">理解React组件</a>
                                <ul class="toc-sublist">
                                    <li class="toc-item">
                                        <a href="#functional-components" class="toc-link">函数组件</a>
                                    </li>
                                    <li class="toc-item">
                                        <a href="#jsx-syntax" class="toc-link">JSX语法</a>
                                    </li>
                                </ul>
                            </li>
                            <li class="toc-item">
                                <a href="#props-and-state" class="toc-link">Props和State</a>
                                <ul class="toc-sublist">
                                    <li class="toc-item">
                                        <a href="#understanding-props" class="toc-link">理解Props</a>
                                    </li>
                                    <li class="toc-item">
                                        <a href="#understanding-state" class="toc-link">理解State</a>
                                    </li>
                                </ul>
                            </li>
                            <li class="toc-item">
                                <a href="#building-todo-app" class="toc-link">构建待办事项应用</a>
                                <ul class="toc-sublist">
                                    <li class="toc-item">
                                        <a href="#project-structure" class="toc-link">项目结构</a>
                                    </li>
                                    <li class="toc-item">
                                        <a href="#implementing-components" class="toc-link">实现组件</a>
                                    </li>
                                </ul>
                            </li>
                            <li class="toc-item">
                                <a href="#handling-events" class="toc-link">处理事件</a>
                                <ul class="toc-sublist">
                                    <li class="toc-item">
                                        <a href="#form-handling" class="toc-link">表单处理</a>
                                    </li>
                                </ul>
                            </li>
                            <li class="toc-item">
                                <a href="#final-app" class="toc-link">完整应用</a>
                            </li>
                            <li class="toc-item">
                                <a href="#conclusion" class="toc-link">总结</a>
                            </li>
                        </ul>
                    </div>
                </aside>
            </div>

            <!-- 相关教程 -->
            <section class="related-tutorials">
                <h2 class="section-title">相关教程</h2>
                <div class="related-grid">
                    <div class="related-card">
                        <h3 class="related-title"><a href="#">React Hooks深入理解</a></h3>
                        <div class="related-meta">
                            <span><i class="far fa-clock"></i> 30分钟</span>
                            <span class="difficulty intermediate">中级</span>
                        </div>
                        <p class="related-excerpt">深入学习React Hooks，包括useState、useEffect、useContext等，以及如何创建自定义Hooks。</p>
                    </div>
                    <div class="related-card">
                        <h3 class="related-title"><a href="#">React Router路由管理</a></h3>
                        <div class="related-meta">
                            <span><i class="far fa-clock"></i> 25分钟</span>
                            <span class="difficulty intermediate">中级</span>
                        </div>
                        <p class="related-excerpt">学习如何在React应用中实现客户端路由，创建单页面应用（SPA）。</p>
                    </div>
                    <div class="related-card">
                        <h3 class="related-title"><a href="#">React状态管理：Redux vs Context API</a></h3>
                        <div class="related-meta">
                            <span><i class="far fa-clock"></i> 40分钟</span>
                            <span class="difficulty advanced">高级</span>
                        </div>
                        <p class="related-excerpt">比较Redux和Context API在React状态管理中的优缺点，并学习何时使用哪种方案。</p>
                    </div>
                </div>
            </section>
        </div>
    </div>

    <footer>
        <div class="container">
            <p>&copy; 2023 TechBlog. 保留所有权利。</p>
        </div>
    </footer>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/highlight.min.js"></script>
    <script>
        // 初始化代码高亮
        hljs.highlightAll();

        // 主题切换功能
        const themeToggle = document.getElementById('themeToggle');
        const themeIcon = themeToggle.querySelector('i');
        const themeText = themeToggle.querySelector('span');

        // 检查本地存储的主题偏好
        if (localStorage.getItem('theme') === 'dark') {
            document.body.classList.add('dark-theme');
            themeIcon.classList.replace('fa-moon', 'fa-sun');
            themeText.textContent = '浅色模式';
        }

        themeToggle.addEventListener('click', () => {
            document.body.classList.toggle('dark-theme');

            if (document.body.classList.contains('dark-theme')) {
                themeIcon.classList.replace('fa-moon', 'fa-sun');
                themeText.textContent = '浅色模式';
                localStorage.setItem('theme', 'dark');
            } else {
                themeIcon.classList.replace('fa-sun', 'fa-moon');
                themeText.textContent = '深色模式';
                localStorage.setItem('theme', 'light');
            }
        });

        // 移动端菜单切换
        const mobileMenu = document.getElementById('mobileMenu');
        const navLinks = document.querySelector('.nav-links');

        mobileMenu.addEventListener('click', () => {
            navLinks.classList.toggle('active');
        });

        // 点赞功能
        const likeBtn = document.getElementById('likeBtn');
        likeBtn.addEventListener('click', () => {
            likeBtn.classList.toggle('liked');
            if (likeBtn.classList.contains('liked')) {
                likeBtn.innerHTML = '<i class="fas fa-thumbs-up"></i> 已点赞';
            } else {
                likeBtn.innerHTML = '<i class="far fa-thumbs-up"></i> 点赞';
            }
        });

        // 收藏功能
        const bookmarkBtn = document.getElementById('bookmarkBtn');
        bookmarkBtn.addEventListener('click', () => {
            bookmarkBtn.classList.toggle('bookmarked');
            if (bookmarkBtn.classList.contains('bookmarked')) {
                bookmarkBtn.innerHTML = '<i class="fas fa-bookmark"></i> 已收藏';
            } else {
                bookmarkBtn.innerHTML = '<i class="far fa-bookmark"></i> 收藏';
            }
        });

        // 标记完成功能
        const completedBtn = document.getElementById('completedBtn');
        completedBtn.addEventListener('click', () => {
            completedBtn.classList.toggle('completed');
            if (completedBtn.classList.contains('completed')) {
                completedBtn.innerHTML = '<i class="fas fa-check-circle"></i> 已完成';
            } else {
                completedBtn.innerHTML = '<i class="far fa-check-circle"></i> 标记完成';
            }
        });

        // 阅读进度条
        window.addEventListener('scroll', () => {
            const winHeight = window.innerHeight;
            const docHeight = document.documentElement.scrollHeight;
            const scrollTop = window.pageYOffset;
            const scrollPercent = (scrollTop / (docHeight - winHeight)) * 100;
            const progressBar = document.getElementById('progressBar');
            progressBar.style.width = scrollPercent + '%';
        });

        // 目录高亮功能 - 修复后的实现
        document.addEventListener('DOMContentLoaded', function () {
            const sections = document.querySelectorAll('h2, h3');
            const tocLinks = document.querySelectorAll('.toc-link');

            // 为每个标题添加观察器
            const observerOptions = {
                root: null,
                rootMargin: '-20% 0px -70% 0px',
                threshold: 0
            };

            const observer = new IntersectionObserver(function (entries) {
                entries.forEach(entry => {
                    const id = entry.target.getAttribute('id');
                    const tocLink = document.querySelector(`.toc-link[href="#${id}"]`);

                    if (entry.isIntersecting) {
                        // 移除所有活动类
                        tocLinks.forEach(link => link.classList.remove('active'));
                        // 添加活动类到当前链接
                        if (tocLink) {
                            tocLink.classList.add('active');

                            // 滚动到活动目录项（如果需要）
                            const tocContainer = document.querySelector('.toc-container');
                            const activeItem = tocLink.parentElement;

                            if (tocContainer && activeItem) {
                                const containerHeight = tocContainer.offsetHeight;
                                const itemOffset = activeItem.offsetTop;
                                const itemHeight = activeItem.offsetHeight;

                                // 如果活动项不在可视区域内，则滚动到它
                                if (itemOffset < tocContainer.scrollTop ||
                                    itemOffset + itemHeight > tocContainer.scrollTop + containerHeight) {
                                    tocContainer.scrollTop = itemOffset - containerHeight / 2 + itemHeight / 2;
                                }
                            }
                        }
                    }
                });
            }, observerOptions);

            // 观察所有标题
            sections.forEach(section => {
                observer.observe(section);
            });

            // 平滑滚动到锚点
            tocLinks.forEach(link => {
                link.addEventListener('click', function (e) {
                    e.preventDefault();

                    const targetId = this.getAttribute('href');
                    const targetElement = document.querySelector(targetId);

                    if (targetElement) {
                        window.scrollTo({
                            top: targetElement.offsetTop - 100,
                            behavior: 'smooth'
                        });
                    }
                });
            });
        });
    </script>
</body>

</html>